#!/usr/bin/env python
# -*- coding: utf-8 -*-

from typing import Any

from cta.interface.action.update_quant2_account.abstract_update_quant2_account_action import \
    AbstractUpdateQuant2AccountAction
from web.constants.datetime_format import DatetimeFormat
from web.constants.direction import Direction
from web.domain.responsibility_chain_dto import ResponsibilityChainDto
from web.manager.log_manager import LogManager
from web.models import CommodityFutureInfo
from web.models.commodity_future_date_contract_data import CommodityFutureDateContractData
from web.models.quant2_account import Quant2Account
from web.models.quant2_commodity_future_transaction_record import Quant2CommodityFutureTransactionRecord
from web.util.commodity_future_code_util import CommodityFutureCodeUtil
from web.util.datetime_util import DatetimeUtil
from web.util.fee_util import FeeUtil

Logger = LogManager.get_logger(__name__)

class UpdateQuant2AccountBeforeClosePositionAction(AbstractUpdateQuant2AccountAction):
    """
    普通的平仓前更新quant2_account表动作
    """

    def exec(self, responsibility_chain_dto: ResponsibilityChainDto = None) -> Any:
        Logger.info("平仓前更新quant2_account表")

        transaction_date: str = responsibility_chain_dto.transaction_date

        # 返回量化账户
        quant2_account_list: list[Quant2Account] = self.quant2_account_dao.find_all()

        for quant2_account in quant2_account_list:
            # 期货资产
            commodity_future_assets: float = 0.0

            # 计算每一个量化账户，在某一天平仓前的收益
            quant2_commodity_future_transaction_record_list: list[Quant2CommodityFutureTransactionRecord] = self.quant2_commodity_future_transaction_record_dao.find_by_account_name_and_not_close_position(quant2_account.account_name)

            if quant2_commodity_future_transaction_record_list is not None and len(quant2_commodity_future_transaction_record_list) > 0:
                for quant2_commodity_future_transaction_record in quant2_commodity_future_transaction_record_list:
                    # 期货收盘价
                    filter_dict: dict = {'code': quant2_commodity_future_transaction_record.code, 'transaction_date': transaction_date}
                    commodity_future_date_contract_data: CommodityFutureDateContractData = self.commodity_future_date_contract_data_dao.find_one(filter_dict, dict(), dict())

                    if commodity_future_date_contract_data is None:
                        # 说明期货在这一天没有交易记录
                        Logger.info("期货[%s]在日期[%s]没有交易记录，开始查找前一个交易日的记录", quant2_commodity_future_transaction_record.code, transaction_date)

                        # 如果在某一天没有开盘价，比如暂停交易，则查找最近一个交易日的开盘价
                        commodity_future_date_contract_data = self.commodity_future_date_contract_data_dao.find_last_commodity_future_date_contract_data_by_code_and_date(quant2_commodity_future_transaction_record.code, transaction_date)

                    # 查询commodity_future_info记录（大小写不敏感的精确匹配查询）
                    filter_dict = {'code__iexact': CommodityFutureCodeUtil.code_to_contract_code(commodity_future_date_contract_data.code)}
                    commodity_future_info: CommodityFutureInfo = self.commodity_future_info_dao.find_one(filter_dict, dict(), list())

                    # 计算这个期货的资产
                    if quant2_commodity_future_transaction_record.direction == Direction.Up:
                        commodity_future_assets = commodity_future_assets + FeeUtil.calculate_open_commodity_future_cost(quant2_commodity_future_transaction_record.buy_price, commodity_future_info, quant2_commodity_future_transaction_record.buy_lot) \
                                                   + FeeUtil.calculate_actual_profit_and_loss(quant2_commodity_future_transaction_record.direction, quant2_commodity_future_transaction_record.buy_price, commodity_future_date_contract_data.close_price, commodity_future_info.transaction_multiplier, quant2_commodity_future_transaction_record.buy_lot)
                    if quant2_commodity_future_transaction_record.direction == Direction.Down:
                        commodity_future_assets = commodity_future_assets + FeeUtil.calculate_open_commodity_future_cost(quant2_commodity_future_transaction_record.sell_price, commodity_future_info, quant2_commodity_future_transaction_record.sell_lot) \
                                                    + FeeUtil.calculate_actual_profit_and_loss(quant2_commodity_future_transaction_record.direction, quant2_commodity_future_transaction_record.sell_price, commodity_future_date_contract_data.close_price, commodity_future_info.transaction_multiplier, quant2_commodity_future_transaction_record.sell_lot)

                # 更新quant2_account表的commodity_future_assets、total_assets字段
                if commodity_future_assets != 0:
                    quant2_account.hold_commodity_future_number = len(quant2_commodity_future_transaction_record_list)
                    quant2_account.commodity_future_assets = commodity_future_assets
                    quant2_account.total_assets = round(float(quant2_account.capital_assets) + commodity_future_assets, 2)
                    self.quant2_account_dao.update(quant2_account)
            else:
                Logger.info("账号[%s]在日期[%s]没有持仓的期货，不用更新quant2_account表", quant2_account.account_name, transaction_date)

        super().next(responsibility_chain_dto)